from tkinter import *                            #tkinter标准库
from tkinter import ttk                          #ttk组件
from tkinter import messagebox                   #消息提示
import tkinter.filedialog                        #文件选择窗口
from tkinter.colorchooser import askcolor        #颜色选择界面
import threading                                 #多线程
import os                                        #os模块
import shutil                                    #高级文件夹操作

from cube import cube as cb
cb = cb()


#####################################################################################################################################################


class CharacterDrawingGui():
    

    def __init__(self,init_window_name):
        """初始化程序"""
        self.init_window_name = init_window_name


#####################################################################################################################################################


    def set_init_window(self):
        """初始化窗口,界面组件"""

        #窗口初始化
        self.init_window_name.protocol('WM_DELETE_WINDOW',self.Exit) #这个很关键,在默认关闭中子线程不会停止,使用[os._exit(0)]结束进程,守护进程不好用
        self.width = 800                                             #设置窗口宽度(可以自定义,后面所有窗口根据这个值进行设置)
        self.height = int((self.width/1.5)-50)                       #根据窗口宽度来设置窗口高度,(保持3:2的关系)减50是减去标题和菜单的宽度
        self.init_window_name.title('字符画生成')                    #窗口名
        self.init_window_name.geometry(f'''{self.width}x{self.height
            }+{int((self.init_window_name.winfo_screenwidth()-self.width)/2)}+{int((self.init_window_name.winfo_screenheight()-self.height)/2)}''')
                                                                     #窗口大小与位置,宽x高+水平方向位置+垂直方向位置(这里是为了让程序窗口在屏幕中间)
        self.init_window_name.minsize(self.width,self.height)        #设置窗口最小值(如果不设置,窗口大小会比预设小)
        self.init_window_name.iconbitmap('logo.ico')                 #左上角的logo图标
        #self.init_window_name.attributes("-alpha",0.9)              #窗口透明度,更改程序的alpha通道的值
        #self.init_window_name.attributes("-topmost",True)           #窗口置顶(False不置顶,True置顶)

        #============================================================================================================================================

        #菜单栏初始化
        self.menu_main =    Menu(self.init_window_name)              #总菜单
        self.menu_pattern = Menu(self.menu_main,tearoff=False)       #转化设置的菜单
        self.menu_json =    Menu(self.menu_main,tearoff=False)       #配置文件的菜单
        self.menu_topmost = Menu(self.menu_main,tearoff=False)       #窗口置顶的菜单

            #窗口置顶
        self.topmost_set = IntVar()
        self.topmost_set.set(0)#设置[窗口置顶]菜单的默认值,当前为[不置顶]
        self.menu_topmost.add_radiobutton(label='不置顶',  var=self.topmost_set,value=0,command=self.Topmost_set)      #窗口置顶中1组件
        self.menu_topmost.add_radiobutton(label='置顶',    var=self.topmost_set,value=1,command=self.Topmost_set)      #窗口置顶中2组件
        self.menu_main.add_cascade(       label='窗口置顶',menu=self.menu_topmost)
            #疑难解答
        self.menu_main.add_cascade(label='疑难解答',command=self.Heelp)
            #关于程序
        self.menu_main.add_cascade(label='关于程序',command=self.About)

        #加载菜单(显示出来)
        self.init_window_name.config(menu=self.menu_main)
        
        #============================================================================================================================================
        self.exponent = 3
        #self.exponent = int(input('请输入魔方阶数:'))
        self.cube = cb.cube_init(self.exponent)
        print(self.cube)
        #魔方展开图
        self.cube_stretch = LabelFrame(text='魔方展开图')
        relief = 'raised'
        #relief = None
        for i in ["R","L","U","D","F","B"]:
            for j in range(1,len(self.cube[0])+1):
                exec(f"self.{i}{j}__label = Label(self.cube_stretch,width=2,relief=relief)")
        del relief
                
        ranks = [[],[],[],[],[],[]]
        for i in range(self.exponent):
            for j in range(self.exponent+1,self.exponent*2+1):
                ranks[0].append([i,j])
        for i in range(4):
            for j in range(self.exponent+1,self.exponent*2+1):
                for k in range(self.exponent*i+i,self.exponent*(i+1)+i):
                    ranks[i+1].append([j,k])
        for i in range(self.exponent*2+2,self.exponent*3+2):
            for j in range(self.exponent+1,self.exponent*2+1):
                ranks[5].append([i,j])
        for i in zip(range(6),["U","L","F","R","B","D"]):
            for j in zip(range(1,len(self.cube[0])+1),ranks[i[0]]):
                exec(f"self.{i[1]}{j[0]}__label.grid(row={j[1][0]},column={j[1][1]})")
        Label(self.cube_stretch,width=2).grid(row=self.exponent,column=0)
        Label(self.cube_stretch,width=2).grid(row=self.exponent*2+1,column=0)
        Label(self.cube_stretch,width=2).grid(row=0,column=self.exponent)
        Label(self.cube_stretch,width=2).grid(row=0,column=self.exponent*2+1)
        Label(self.cube_stretch,width=2).grid(row=0,column=self.exponent*3+2)
        

        console_fun =[]
        for i in range(1,self.exponent//2+1):
            for j in ["U","L","F","R","B","D"]:
                for k in zip(["","2","'"],[1,2,3]):
                    if i == 1:
                        console_fun.append([j+k[0],"F_"+str(i)+j+"w"+str(k[1])])
                    else:
                        console_fun.append([str(i)+j+"w"+k[0],"F_"+str(i)+j+"w"+str(k[1])])
        #print(console_fun)
        #控制台
        self.console = LabelFrame(text='公式控制台')
        for i in zip(console_fun,range(len(console_fun))):
            ttk.Button(self.console,text=i[0][0], command=lambda arg=i[0][0]:self.addfun(arg),width=8).grid(row=i[1]//6,column=i[1]%6)

        self.La_fun = LabelFrame(text='公式')
        self.fun__entry = Entry(self.La_fun,bg='#DCDCDC')
        self.fun__button = ttk.Button(self.La_fun,text='运行公式',command=self.funrun,width=10)
        self.res__button = ttk.Button(self.La_fun,text='一键还原',command=self.res,width=10)
        self.fun__entry.grid(row=0,column=0)
        self.fun__button.grid(row=0,column=1)
        self.res__button.grid(row=0,column=2)


        self.cube_stretch.grid(row=0,column=0)
        self.console.grid(row=0,column=1)
        self.La_fun.grid(row=1,column=1)
        self.cube_display(cb.cube_init(self.exponent))

    def cube_display(self,cube):
        """魔方展开图显示"""
        cube_compare = ["-1","white","green","red","yellow","blue","orange"]
        cube_compare = ["-1","#ffffff","#00ff00","#ff0000","#ffff00","#0000ff","#ff7f00"]
        for i in zip(["F","R","U","B","L","D"],range(6)):
            for j in range(len(cube[0])):
                exec(f"self.{i[0]}{j+1}__label['bg'] = cube_compare[cube[i[1]][j]]")
                #exec(f"self.{i[0]}{j+1}__label['text'] = cube[i[1]][j]")
                #print(cube[i[1]][j][0])
        del cube_compare , cube

    def addfun(self,fun):
        self.cube = cb.fun_run(cb.fun_split(fun),self.cube,self.exponent)
        self.cube_display(self.cube)
        #print(cb.cube_format(self.cube))

    def res(self):
        self.cube = cb.cube_init(self.exponent)
        self.cube_display(self.cube)
        
    def funrun(self):
        fun = self.fun__entry.get()
        #print(cb.fun_split(fun))
        self.cube = cb.fun_run(cb.fun_split(fun),self.cube,self.exponent)
        self.cube_display(self.cube)
        self.fun__entry.delete('0','end')

    def Topmost_set(self):
        """窗口置顶"""
        #窗口置顶(False不置顶,True置顶)
        if self.topmost_set.get() == 0:
            self.init_window_name.attributes("-topmost",False)
            try:self.heelp_window.attributes("-topmost",False)
            except:pass
            try:self.about_window.attributes("-topmost",False)
            except:pass
        elif self.topmost_set.get() == 1:
            self.init_window_name.attributes("-topmost",True)
            try:self.heelp_window.attributes("-topmost",True)
            except:pass
            try:self.about_window.attributes("-topmost",True)
            except:pass


    def Heelp(self):
        """疑难解答"""
        try:self.heelp_window.destroy()#只允许一个窗口,当有这个窗口时关闭这个窗口,然后重新创建
        except:pass
        self.heelp_window = Toplevel()
        self.heelp_window.title('疑难解答')                     #窗口名
        self.heelp_window.geometry(f'''{self.init_window_name.winfo_width()}x{self.init_window_name.winfo_height()-10
                    }+{self.init_window_name.winfo_x()}+{self.init_window_name.winfo_y()+30}''')#窗口大小,宽x高+水平方向位置+垂直方向位置
        self.heelp_window.iconbitmap('logo.ico')                #左上角图标
        self.heelp_window.minsize(self.width,self.height-10)    #设置窗口最小值,太小显示会出错
        if self.topmost_set.get() == 1:
            self.heelp_window.attributes("-topmost",True)#窗口置顶
            #滚动条和文本框窗口
        self.heep__scrollbar = Scrollbar(self.heelp_window)
        self.heep__text = Text(self.heelp_window,bg='#F0F0F0',bd=0,yscrollcommand=self.heep__scrollbar.set,font=('NSimSun',10))
        self.heep__scrollbar.config(command = self.heep__text.yview)
            #pack布局,因为可以随窗口大小自适应
            #关于pack参数请注意:单词小写时需要使用字符串格式，若为大写单词则不必使用字符串格式
        self.heep__scrollbar.pack(fill=Y,side='right')
        self.heep__text.pack(fill=BOTH,expand=True)
            #显示内容
        self.heep__text.insert(END,open('./疑难解答.txt','r',encoding='utf-8').read())#内容可能有亿点点多所以采用读取txt
        self.heep__text.config(state='disabled')#不可以修改,但可以选中复制


    def About(self):
        """关于程序"""
        try:self.about_window.destroy()#只允许一个窗口,当有这个窗口时关闭这个窗口,然后重新创建
        except:pass
        self.about_window = Toplevel()
        self.about_window.title('关于程序')                     #窗口名
        self.about_window.geometry(f'''{self.init_window_name.winfo_width()}x{self.init_window_name.winfo_height()-10
                    }+{self.init_window_name.winfo_x()}+{self.init_window_name.winfo_y()+30}''')#窗口大小,宽x高+水平方向位置+垂直方向位置
        self.about_window.iconbitmap('logo.ico')                #左上角图标
        self.about_window.minsize(self.width,self.height-10)    #设置窗口最小值,太小显示会出错
        if self.topmost_set.get() == 1:
            self.about_window.attributes("-topmost",True)#窗口置顶
            #滚动条和文本框窗口
        self.about__scrollbar = Scrollbar(self.about_window)
        self.about__text = Text(self.about_window,bg='#F0F0F0',bd=0,yscrollcommand=self.about__scrollbar.set,font=('NSimSun',22))
        self.about__scrollbar.config(command = self.about__text.yview)
            #pack布局,因为可以随窗口大小自适应
            #关于pack参数请注意:单词小写时需要使用字符串格式，若为大写单词则不必使用字符串格式
        self.about__scrollbar.pack(fill=Y,side='right')
        self.about__text.pack(fill=BOTH,expand=True)
            #显示内容
        self.about__text.insert(END,open('./关于程序.txt','r',encoding='utf-8').read())#内容可能有亿点点多所以采用读取txt
        self.about__text.config(state='disabled')#不可以修改,但可以选中复制

#====================================================================================================================================================

    #强制关闭函数------------------------------------------------------------------------------------------------------------------------------------
    def Exit(self):
        """结束进程"""
        os._exit(0)


#####################################################################################################################################################


if __name__ == '__main__':
    init_window = Tk()
    portal = CharacterDrawingGui(init_window)
    portal.set_init_window()       #窗口组件加载
    init_window.mainloop()         #gui窗口进入循环,开始运行
